package com.sky.wsp.guo.mi.utils;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;

public class SM4PasswordEncoder implements PasswordEncoder {

    @Override
    public String encode(CharSequence rawPassword) {
        return SM4Util.enc(rawPassword.toString());
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        return SM4Util.dec(encodedPassword).equals(rawPassword.toString());
    }

    private class SM4Util {
        private static Cipher encryptCipher;
        private static Cipher decryptCipher;

        static {
            Security.addProvider(new BouncyCastleProvider());
            try {
                // 注意： key的秘钥位数需要是 16因为   128位/8 = 16
                SecretKeySpec secretKey = new SecretKeySpec("1234567890AbCdEf".getBytes(), "SM4");
                // 生成初始化向量 (IV)
                IvParameterSpec ivSpec = new IvParameterSpec("AbCdEf1234567890".getBytes());

                // 加密
                encryptCipher = Cipher.getInstance("SM4/CBC/PKCS5Padding");
                encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);

                // 解密
                decryptCipher = Cipher.getInstance("SM4/CBC/PKCS5Padding");
                decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public static String enc(String str) {
            try {
                byte[] cipherText = encryptCipher.doFinal(str.getBytes());
                return HexUtil.encode(cipherText);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        public static String dec(String str) {
            try {
                byte[] decodeBytes = HexUtil.decode(str);
                byte[] decryptedText = decryptCipher.doFinal(decodeBytes);
                return new String(decryptedText);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}